package com.zxjbyte.yiyi.extension.job.core;

import com.zxjbyte.yiyi.extension.job.core.trigger.TriggerArgs;
import com.zxjbyte.yiyi.extension.job.core.trigger.TriggerKeyBuilder;
import com.zxjbyte.yiyi.extension.job.core.trigger.route.CronTriggerHelper;
import com.zxjbyte.yiyi.extension.job.enums.JobDataKeyEnum;
import com.zxjbyte.yiyi.extension.job.enums.TriggerTypeEnum;
import com.zxjbyte.yiyi.framework.common.core.BaseArgs;
import com.zxjbyte.yiyi.framework.common.util.JsonUtil;
import com.zxjbyte.yiyi.framework.common.util.ValidationUtil;

import com.zxjbyte.yiyi.extension.job.core.alarm.AlarmPayload;
import lombok.Data;
import org.quartz.*;

import java.util.Date;
import java.util.Map;

/**
 * 编辑任务参数类
 *
 * @Author zhangxingjia
 * @Date 2023/11/9 19:59
 * @Version: 1.0
 */
@Data
public class ObjectJobUpdateArgs extends TriggerArgs {

    // 需要更新的老的触发器键
    private TriggerKey oldTriggerKey;

    /**
     * 构建Builder
     * @return
     */
    public static ObjectJobUpdateArgs.Builder newBuilder(){
        return new ObjectJobUpdateArgs.Builder();
    }

    public static class Builder extends BaseArgs.Builder<ObjectJobUpdateArgs.Builder, ObjectJobUpdateArgs> {

        @Override
        protected void validate(ObjectJobUpdateArgs args) {
            ValidationUtil.assertNotNull(args.getScheduleBuilder(), "JobUpdate ScheduleBuilder");
            ValidationUtil.assertNotNull(args.getOldTriggerKey(), "JobUpdate oldTriggerKey");
            // 未设定新的TriggerKey则与老的TriggerKey保持一致
            if(args.getTriggerKey() == null){
                args.setTriggerKey(args.getOldTriggerKey());
            }
        }

        public Builder oldTriggerKey(TriggerKey oldTriggerKey){
            operations.add(args -> args.oldTriggerKey = oldTriggerKey);
            return this;
        }

        public Builder oldTriggerKey(String oldTriggerName, String... oldTriggerGroup){
            return oldTriggerKey(TriggerKeyBuilder.newTriggerKey(oldTriggerName, oldTriggerGroup));
        }

        public Builder failRetryCount(Boolean condition, Integer retryCount){
            if(Boolean.TRUE.equals(condition) && retryCount != null && retryCount > 0){
                return jobData(JobDataKeyEnum.FAIL_RETRY_COUNT.name(), retryCount);
            }
            return this;
        }

        public Builder alarmEmail(Boolean condition, AlarmPayload alarmPayload){
            if(Boolean.TRUE.equals(condition)){
                return jobData(JobDataKeyEnum.EMAIL_ALARM.name(), JsonUtil.toJsonAsString(alarmPayload));
            }
            return this;
        }

        public Builder jobLog(Boolean condition){
            if(Boolean.TRUE.equals(condition)){
                return jobData(JobDataKeyEnum.NEED_RECORD_LOG.name(), true);
            }
            return this;
        }

        public Builder failRetryCount(Integer retryCount){
            return failRetryCount(true, retryCount);
        }

        public Builder retryInterval(Boolean condition, Long millis){
            if(Boolean.TRUE.equals(condition) && millis != null){
                return jobData(JobDataKeyEnum.RETRY_INTERVAL_IN_MILLIS.name(), millis);
            }
            return this;
        }

        public Builder retryInterval(Long millis){
            return retryInterval(true, millis);
        }

        public Builder jobClassName(String className){
            return jobData(JobDataKeyEnum.JOB_CLASS_NAME.name(), className);
        }

        public Builder jobMethodName(String methodName){
            return jobData(JobDataKeyEnum.JOB_METHOD_NAME.name(), methodName);
        }

        public Builder methodParam(boolean condition, Object methodParam){
            if(condition){
                return jobData(JobDataKeyEnum.METHOD_PARAM.name(), methodParam);
            }
            return this;
        }

        public Builder methodParam(Object methodParam){
            return methodParam(true, methodParam);
        }


        public Builder cronExpression(String cronExpression){
            return cronExpression(CronTriggerHelper.customCronSchedule(cronExpression));
        }

        public Builder cronExpression(CronScheduleBuilder cronScheduleBuilder){
            return scheduleBuilder(TriggerTypeEnum.CRON, cronScheduleBuilder);
        }

        public Builder scheduleBuilder(TriggerTypeEnum triggerTypeEnum, ScheduleBuilder<? extends Trigger> scheduleBuilder){
            operations.add(args -> args.triggerTypeEnum = triggerTypeEnum);
            operations.add(args -> args.scheduleBuilder = scheduleBuilder);
            return this;
        }

        public Builder triggerDescription(String triggerDescription){
            operations.add(args -> args.triggerDescription = triggerDescription);
            return this;
        }

        public Builder triggerEndTime(Date triggerEndTime){
            operations.add(args -> args.triggerEndTime = triggerEndTime);
            return this;
        }

        public Builder triggerStartTime(Date triggerStartTime){
            operations.add(args -> args.triggerStartTime = triggerStartTime);
            return this;
        }

        public Builder triggerStartNow(){
            operations.add(args -> args.triggerStartNow = true);
            return this;
        }

        public Builder triggerKey(TriggerKey triggerKey){
            operations.add(args -> args.triggerKey = triggerKey);
            return this;
        }

        public Builder triggerKey(String name, String group){
            operations.add(args -> args.triggerKey = TriggerKeyBuilder.newTriggerKey(name, group));
            return this;
        }

        public Builder triggerKey(String name){
            operations.add(args -> args.triggerKey = TriggerKeyBuilder.newTriggerKey(name));
            return this;
        }

        public Builder jobDataMap(Map<String, Object> map){
            operations.add(args -> args.jobDataMap.putAll(map));
            return this;
        }

        public Builder jobData(String dataKey, Object value){
            operations.add(args -> args.jobDataMap.put(dataKey, value));
            return this;
        }

        public Builder jobData(String dataKey, String value){
            operations.add(args -> args.jobDataMap.put(dataKey, value));
            return this;
        }

        public Builder jobData(String dataKey, int value){
            operations.add(args -> args.jobDataMap.put(dataKey, value));
            return this;
        }

        public Builder jobData(String dataKey, long value){
            operations.add(args -> args.jobDataMap.put(dataKey, value));
            return this;
        }

        public Builder jobData(String dataKey, boolean value){
            operations.add(args -> args.jobDataMap.put(dataKey, value));
            return this;
        }

        public Builder jobData(String dataKey, double value){
            operations.add(args -> args.jobDataMap.put(dataKey, value));
            return this;
        }

        public Builder jobData(String dataKey, float value){
            operations.add(args -> args.jobDataMap.put(dataKey, value));
            return this;
        }
    }
}
